}
#ifdef HAVE_CUPS_API_1_6
-typedef struct
-{
- gchar *name;
- gchar *type;
- gchar *domain;
- gchar *host;
- gint port;
-} AvahiService;
-
-void
-avahi_service_free (AvahiService *service)
-{
- if (service)
- {
- g_free (service->name);
- g_free (service->type);
- g_free (service->domain);
- g_free (service->host);
- g_free (service);
- }
-}
-
static void
cups_request_avahi_printer_info_cb (GtkPrintBackendCups *cups_backend,
GtkCupsResult *result,
PrinterSetupInfo *info = g_slice_new0 (PrinterSetupInfo);
GtkPrintBackend *backend = GTK_PRINT_BACKEND (cups_backend);
ipp_attribute_t *attr;
- AvahiService *service = (AvahiService *) user_data;
GtkPrinter *printer;
- gboolean list_has_changed = FALSE;
gboolean status_changed = FALSE;
ipp_t *response;
if (info->printer_name && info->printer_uri)
{
- info->avahi_printer = TRUE;
-
- if (info->got_printer_type &&
- info->default_printer &&
- cups_backend->avahi_default_printer == NULL)
- cups_backend->avahi_default_printer = g_strdup (info->printer_name);
-
set_info_state_message (info);
printer = gtk_print_backend_find_printer (backend, info->printer_name);
- if (!printer)
+ if (printer != NULL &&
+ GTK_PRINTER_CUPS (printer)->avahi_browsed)
{
- printer = cups_create_printer (cups_backend, info);
- list_has_changed = TRUE;
+ g_object_ref (printer);
}
else
{
- g_object_ref (printer);
+ goto done;
}
+ if (info->got_printer_type &&
+ info->default_printer &&
+ cups_backend->avahi_default_printer == NULL)
+ cups_backend->avahi_default_printer = g_strdup (info->printer_name);
+
gtk_printer_set_is_paused (printer, info->is_paused);
gtk_printer_set_is_accepting_jobs (printer, info->is_accepting_jobs);
- if (!gtk_printer_is_active (printer))
- {
- gtk_printer_set_is_active (printer, TRUE);
- gtk_printer_set_is_new (printer, TRUE);
- list_has_changed = TRUE;
- }
-
GTK_PRINTER_CUPS (printer)->remote = info->remote_printer;
- GTK_PRINTER_CUPS (printer)->avahi_name = g_strdup (service->name);
- GTK_PRINTER_CUPS (printer)->avahi_type = g_strdup (service->type);
- GTK_PRINTER_CUPS (printer)->avahi_domain = g_strdup (service->domain);
- GTK_PRINTER_CUPS (printer)->hostname = g_strdup (service->host);
- GTK_PRINTER_CUPS (printer)->port = service->port;
GTK_PRINTER_CUPS (printer)->state = info->state;
GTK_PRINTER_CUPS (printer)->ipp_version_major = info->ipp_version_major;
GTK_PRINTER_CUPS (printer)->ipp_version_minor = info->ipp_version_minor;
set_printer_icon_name_from_info (printer, info);
- if (gtk_printer_is_new (printer))
- {
- g_signal_emit_by_name (backend, "printer-added", printer);
- gtk_printer_set_is_new (printer, FALSE);
- }
+ gtk_printer_set_has_details (printer, TRUE);
+ g_signal_emit_by_name (printer, "details-acquired", TRUE);
if (status_changed)
g_signal_emit_by_name (GTK_PRINT_BACKEND (backend),
}
done:
- if (list_has_changed)
- g_signal_emit_by_name (backend, "printer-list-changed");
-
if (!cups_backend->got_default_printer &&
gtk_print_backend_printer_list_is_done (backend) &&
cups_backend->avahi_default_printer != NULL)
set_default_printer (cups_backend, cups_backend->avahi_default_printer);
}
+ g_free (info->state_msg);
g_slice_free (PrinterSetupInfo, info);
gdk_threads_leave ();
cups_request_avahi_printer_info (const gchar *printer_uri,
const gchar *host,
gint port,
- const gchar *name,
- const gchar *type,
- const gchar *domain,
GtkPrintBackendCups *backend)
{
GtkCupsRequest *request;
- AvahiService *service;
http_t *http;
http = httpConnect (host, port);
if (http)
{
- service = (AvahiService *) g_new0 (AvahiService, 1);
- service->name = g_strdup (name);
- service->type = g_strdup (type);
- service->domain = g_strdup (domain);
- service->host = g_strdup (host);
- service->port = port;
-
request = gtk_cups_request_new_with_username (http,
GTK_CUPS_POST,
IPP_GET_PRINTER_ATTRIBUTES,
cups_request_execute (backend,
request,
(GtkPrintCupsResponseCallbackFunc) cups_request_avahi_printer_info_cb,
- service,
- (GDestroyNotify) avahi_service_free);
+ NULL,
+ NULL);
}
}
typedef struct
{
gchar *printer_uri;
+ gchar *location;
gchar *host;
gint port;
+ gchar *printer_name;
gchar *name;
+ gboolean got_printer_type;
+ guint printer_type;
+ gboolean got_printer_state;
+ guint printer_state;
gchar *type;
gchar *domain;
GtkPrintBackendCups *backend;
} AvahiConnectionTestData;
+/*
+ * Create new GtkPrinter from informations included in TXT records.
+ */
+static void
+create_cups_printer_from_avahi_data (AvahiConnectionTestData *data)
+{
+ PrinterSetupInfo *info = g_slice_new0 (PrinterSetupInfo);
+ GtkPrinter *printer;
+
+ info->avahi_printer = TRUE;
+ info->printer_name = data->printer_name;
+ info->printer_uri = data->printer_uri;
+
+ if (data->got_printer_state)
+ info->state = data->printer_state;
+
+ info->got_printer_type = data->got_printer_type;
+ if (data->got_printer_type)
+ {
+ if (data->printer_type & CUPS_PRINTER_DEFAULT)
+ info->default_printer = TRUE;
+ else
+ info->default_printer = FALSE;
+
+ if (data->printer_type & CUPS_PRINTER_REMOTE)
+ info->remote_printer = TRUE;
+ else
+ info->remote_printer = FALSE;
+
+ if (data->printer_type & CUPS_PRINTER_REJECTING)
+ info->is_accepting_jobs = FALSE;
+ else
+ info->is_accepting_jobs = TRUE;
+
+ if (info->default_printer &&
+ data->backend->avahi_default_printer == NULL)
+ data->backend->avahi_default_printer = g_strdup (info->printer_name);
+ }
+
+ set_info_state_message (info);
+
+ printer = gtk_print_backend_find_printer (GTK_PRINT_BACKEND (data->backend), data->printer_name);
+ if (printer == NULL)
+ {
+ printer = cups_create_printer (data->backend, info);
+
+ if (data->got_printer_type)
+ {
+ gtk_printer_set_is_accepting_jobs (printer, info->is_accepting_jobs);
+ GTK_PRINTER_CUPS (printer)->remote = info->remote_printer;
+
+ if (info->default_printer &&
+ data->backend->avahi_default_printer == NULL)
+ data->backend->avahi_default_printer = g_strdup (info->printer_name);
+ }
+
+ if (data->got_printer_state)
+ GTK_PRINTER_CUPS (printer)->state = info->state;
+
+ GTK_PRINTER_CUPS (printer)->avahi_name = g_strdup (data->name);
+ GTK_PRINTER_CUPS (printer)->avahi_type = g_strdup (data->type);
+ GTK_PRINTER_CUPS (printer)->avahi_domain = g_strdup (data->domain);
+ g_free (GTK_PRINTER_CUPS (printer)->hostname);
+ GTK_PRINTER_CUPS (printer)->hostname = g_strdup (data->host);
+ GTK_PRINTER_CUPS (printer)->port = data->port;
+ gtk_printer_set_location (printer, data->location);
+ gtk_printer_set_state_message (printer, info->state_msg);
+
+ set_printer_icon_name_from_info (printer, info);
+
+ if (!gtk_printer_is_active (printer))
+ gtk_printer_set_is_active (printer, TRUE);
+
+ g_signal_emit_by_name (data->backend, "printer-added", printer);
+ gtk_printer_set_is_new (printer, FALSE);
+ g_signal_emit_by_name (data->backend, "printer-list-changed");
+
+ if (!data->backend->got_default_printer &&
+ gtk_print_backend_printer_list_is_done (GTK_PRINT_BACKEND (data->backend)) &&
+ data->backend->avahi_default_printer != NULL)
+ set_default_printer (data->backend, data->backend->avahi_default_printer);
+
+ /* The ref is held by GtkPrintBackend, in add_printer() */
+ g_object_unref (printer);
+ }
+
+ g_free (info->state_msg);
+ g_slice_free (PrinterSetupInfo, info);
+}
+
static void
avahi_connection_test_cb (GObject *source_object,
GAsyncResult *res,
g_io_stream_close (G_IO_STREAM (connection), NULL, NULL);
g_object_unref (connection);
- cups_request_avahi_printer_info (data->printer_uri,
- data->host,
- data->port,
- data->name,
- data->type,
- data->domain,
- data->backend);
+ create_cups_printer_from_avahi_data (data);
}
g_free (data->printer_uri);
+ g_free (data->location);
g_free (data->host);
+ g_free (data->printer_name);
g_free (data->name);
g_free (data->type);
g_free (data->domain);
g_free (data);
}
+gboolean
+avahi_txt_get_key_value_pair (const gchar *entry,
+ gchar **key,
+ gchar **value)
+{
+ const gchar *equal_sign;
+
+ *key = NULL;
+ *value = NULL;
+
+ if (entry != NULL)
+ {
+ /* See RFC 6763 section 6.3 */
+ equal_sign = strstr (entry, "=");
+
+ if (equal_sign != NULL)
+ {
+ *key = g_strndup (entry, equal_sign - entry);
+ *value = g_strdup (equal_sign + 1);
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
static void
avahi_service_resolver_cb (GObject *source_object,
GAsyncResult *res,
guint32 flags;
guint16 port;
GError *error = NULL;
- gchar *suffix = NULL;
+ gchar *queue_name = NULL;
gchar *tmp;
+ gchar *printer_name;
+ gchar *endptr;
+ gchar *key;
+ gchar *value;
gint interface;
gint protocol;
gint aprotocol;
&txt,
&flags);
+ data = g_new0 (AvahiConnectionTestData, 1);
+
for (i = 0; i < g_variant_n_children (txt); i++)
{
child = g_variant_get_child_value (txt, i);
tmp[j] = g_variant_get_byte (g_variant_get_child_value (child, j));
}
- if (g_str_has_prefix (tmp, "rp="))
+ if (!avahi_txt_get_key_value_pair (tmp, &key, &value))
{
- suffix = g_strdup (tmp + 3);
g_free (tmp);
- break;
+ continue;
}
+ if (g_strcmp0 (key, "rp") == 0)
+ {
+ queue_name = g_strdup (value);
+
+ printer_name = g_strrstr (queue_name, "/");
+ if (printer_name != NULL)
+ data->printer_name = g_strdup (printer_name + 1);
+ else
+ data->printer_name = g_strdup (queue_name);
+ }
+ else if (g_strcmp0 (key, "note") == 0)
+ {
+ data->location = g_strdup (value);
+ }
+ else if (g_strcmp0 (key, "printer-type") == 0)
+ {
+ endptr = NULL;
+ data->printer_type = g_ascii_strtoull (value, &endptr, 16);
+ if (data->printer_type != 0 || endptr != value)
+ data->got_printer_type = TRUE;
+ }
+ else if (g_strcmp0 (key, "printer-state") == 0)
+ {
+ endptr = NULL;
+ data->printer_state = g_ascii_strtoull (value, &endptr, 10);
+ if (data->printer_state != 0 || endptr != value)
+ data->got_printer_state = TRUE;
+ }
+
+ g_clear_pointer (&key, g_free);
+ g_clear_pointer (&value, g_free);
g_free (tmp);
}
- if (suffix)
+ if (queue_name)
{
if (g_strcmp0 (type, "_ipp._tcp") == 0)
protocol_string = "ipp";
else
protocol_string = "ipps";
- data = g_new0 (AvahiConnectionTestData, 1);
-
if (aprotocol == AVAHI_PROTO_INET6)
- data->printer_uri = g_strdup_printf ("%s://[%s]:%u/%s", protocol_string, address, port, suffix);
+ data->printer_uri = g_strdup_printf ("%s://[%s]:%u/%s", protocol_string, address, port, queue_name);
else
- data->printer_uri = g_strdup_printf ("%s://%s:%u/%s", protocol_string, address, port, suffix);
+ data->printer_uri = g_strdup_printf ("%s://%s:%u/%s", protocol_string, address, port, queue_name);
data->host = g_strdup (address);
data->port = port;
+
data->name = g_strdup (name);
data->type = g_strdup (type);
data->domain = g_strdup (domain);
backend->avahi_cancellable,
avahi_connection_test_cb,
data);
- g_free (suffix);
+ g_free (queue_name);
+ }
+ else
+ {
+ g_free (data->printer_name);
+ g_free (data->location);
+ g_free (data);
}
g_variant_unref (output);
{
gboolean success = FALSE;
- /* If we get a 404 then it is just a raw printer without a ppd
- and not an error. Standalone Avahi printers also don't have
- PPD files. */
- if (((gtk_cups_result_get_error_type (result) == GTK_CUPS_ERROR_HTTP) &&
- (gtk_cups_result_get_error_status (result) == HTTP_NOT_FOUND))
#ifdef HAVE_CUPS_API_1_6
- || GTK_PRINTER_CUPS (printer)->avahi_browsed
+ /* Standalone Avahi printers don't have PPD files. */
+ if (GTK_PRINTER_CUPS (printer)->avahi_browsed)
+ {
+ cups_request_avahi_printer_info (GTK_PRINTER_CUPS (printer)->printer_uri,
+ GTK_PRINTER_CUPS (printer)->hostname,
+ GTK_PRINTER_CUPS (printer)->port,
+ GTK_PRINT_BACKEND_CUPS (gtk_printer_get_backend (printer)));
+ }
+ else
#endif
- )
{
- gtk_printer_set_has_details (printer, TRUE);
- success = TRUE;
+ /* If we get a 404 then it is just a raw printer without a ppd
+ and not an error. */
+ if ((gtk_cups_result_get_error_type (result) == GTK_CUPS_ERROR_HTTP) &&
+ (gtk_cups_result_get_error_status (result) == HTTP_NOT_FOUND))
+ {
+ gtk_printer_set_has_details (printer, TRUE);
+ success = TRUE;
+ }
+
+ g_signal_emit_by_name (printer, "details-acquired", success);
}
- g_signal_emit_by_name (printer, "details-acquired", success);
goto done;
}
GTK_NOTE (PRINTING,
g_print ("CUPS Backend: %s\n", G_STRFUNC));
- if (cups_printer->remote)
+ if (cups_printer->remote
+#ifdef HAVE_CUPS_API_1_6
+ && !cups_printer->avahi_browsed
+#endif
+ )
{
GtkCupsConnectionState state;
if (!cups_printer->reading_ppd &&
gtk_printer_cups_get_ppd (cups_printer) == NULL)
{
- if (cups_printer->remote)
+ if (cups_printer->remote
+#ifdef HAVE_CUPS_API_1_6
+ && !cups_printer->avahi_browsed
+#endif
+ )
{
if (cups_printer->get_remote_ppd_poll == 0)
{